 package br.com.actionsystem.gdp.modelo;
 import java.awt.Color;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.text.*;

 public class AutoCompletar extends PlainDocument {
     JComboBox comboBox;
     ComboBoxModel model;
 //    JTextComponent editor;
     JTextComponent editor;
     // flag to indicate if setSelectedItem has been called
     // subsequent calls to remove/insertString should be ignored
     boolean selecting=false;
     boolean hidePopupOnFocusLoss;
     boolean hitBackspace=false;
     boolean hitBackspaceOnSelection;
     boolean listContainsSelectedItem;

     public AutoCompletar(final JComboBox comboBox) {
         this.comboBox = comboBox;
         model = comboBox.getModel();
         editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
         editor.setDocument(this);
        comboBox.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
                 if (!selecting) highlightCompletedText(0);
             }
         });
         editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                 if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
                 hitBackspace=false;
                 switch (e.getKeyCode()) {
                     // determine if the pressed key is backspace (needed by the remove method)
                     case KeyEvent.VK_BACK_SPACE : hitBackspace=true;
                     hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
                     break;
                 }
             }
         });
         // Bug 5100422 on Java 1.5: Editable JComboBox won't hide popup when tabbing out
         hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
        // Highlight whole text when gaining focus
         editor.addFocusListener(new FocusAdapter() {
             public void focusGained(FocusEvent e) {
                 highlightCompletedText(0);
                 editor.setBackground(Color.white);
             }
            public void focusLost(FocusEvent e) {
                 // Workaround for Bug 5100422 - Hide Popup on focus loss
                if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
             }
         });
         // Handle initially selected object
         Object selected = comboBox.getSelectedItem();
         if (selected!=null) setText(selected.toString());
         highlightCompletedText(0);
     }

     public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
         // return immediately when selecting an item
         if (selecting) return;
         // insert the string into the document
         super.insertString(offs, str, a);
         // lookup and select a matching item
         Object item = lookupItem(getText(0, getLength()));

         listContainsSelectedItem = true;
         if (item == null) {
             // no item matches => use the current input as selected item
             item=getText(0, getLength());
             listContainsSelectedItem=false;
         }
         setSelectedItem(item);
         setText(item.toString());
         // select the completed part
         if (listContainsSelectedItem) highlightCompletedText(offs+str.length());
     }

     private void setText(String text) {
         try {
             // remove all text and insert the completed string
             super.remove(0, getLength());
             super.insertString(0, text, null);
         } catch (BadLocationException e) {
             throw new RuntimeException(e.toString());
         }
     }

     private void highlightCompletedText(int start) {
         editor.setCaretPosition(getLength());
         editor.moveCaretPosition(start);
     }

     private void setSelectedItem(Object item) {
         selecting = true;
         model.setSelectedItem(item);
         selecting = false;
     }

     private Object lookupItem(String pattern) {
         Object selectedItem = model.getSelectedItem();
         // only search for a different item if the currently selected does not match
         if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern) && listContainsSelectedItem) {
             return selectedItem;
         } else {
             // iterate over all items
             for (int i=0, n=model.getSize(); i < n; i++) {
                 Object currentItem = model.getElementAt(i);
                 // current item starts with the pattern?
                 if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                     return currentItem;
                 }
             }
         }
         // no item starts with the pattern => return null
         return null;
     }

     // checks if str1 starts with str2 - ignores case
     private boolean startsWithIgnoreCase(String str1, String str2) {
         return str1.toUpperCase().startsWith(str2.toUpperCase());
     }



 }